from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

from utils.filters import FILTERS
from flask_apscheduler import APScheduler
from flask_login import LoginManager

from flask_wtf import CSRFProtect



# 初始化 SQLAlchemy 对象
db = SQLAlchemy()
migrate = Migrate()
# 实例化调度器
scheduler = APScheduler()

# 实例化鉴权对象
login_manager = LoginManager()
login_manager.login_view = 'admin.login'


csrf = CSRFProtect()

# 工厂函数模式(一般是用于项目初始化或者数据库创建)
def create_app():
    app = Flask(__name__)

    # 加载配置文件
    # 如果设置为 silent=True，则在加载 settings.py 文件时出现错误时不会抛出异常，而是继续执行后续代码
    # 如果设置为 silent=False，则会抛出异常并中断程序执行
    app.config.from_pyfile('settings.py', silent=True)


    # 初始化数据库, 注册ORM到app
    db.init_app(app)
    # 注册迁移对象
    migrate.init_app(app, db)
    # 注册调度器
    scheduler.init_app(app)
    # 启动调度器
    scheduler.start()
    # 注册flask_login
    login_manager.init_app(app)
    csrf.init_app(app)

    # 引入blog视图 (这个引入必须放在create_app里面)
    from app.blog import views as blog  # 应用上下文
    from app.admin import views as admin  # 应用上下文
    # 注册蓝图
    app.register_blueprint(blog.bp)
    app.register_blueprint(admin.bp)

    # 注册首页根路由url规则
    app.add_url_rule(rule='/', endpoint='index', view_func=blog.index)

    # 在app所在的上下文中, 注册数据模型
    from app.blog import models
    from app.admin import models

    # 过滤器注册
    for key, value in FILTERS.items():
        app.add_template_filter(value, key)
    return app